home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / leland.c < prev    next >
C/C++ Source or Header  |  2000-05-18  |  21KB  |  856 lines

  1. /***************************************************************************
  2.  
  3.     Cinemat/Leland driver
  4.  
  5.     Leland video hardware
  6.     driver by Aaron Giles and Paul Leaman
  7.  
  8. ***************************************************************************/
  9.  
  10. #ifndef INCLUDE_DRAW_CORE
  11.  
  12. #include "driver.h"
  13. #include "vidhrdw/generic.h"
  14.  
  15. #include "osdepend.h"
  16.  
  17.  
  18. /* constants */
  19. #define VRAM_LO     0x00000
  20. #define VRAM_HI     0x08000
  21. #define VRAM_SIZE    0x10000
  22.  
  23. #define QRAM_SIZE    0x10000
  24.  
  25. #define VIDEO_WIDTH  0x28
  26. #define VIDEO_HEIGHT 0x1e
  27.  
  28.  
  29. /* debugging */
  30. #define LOG_COMM    0
  31.  
  32.  
  33.  
  34. struct vram_state_data
  35. {
  36.     UINT16    addr;
  37.     UINT8    plane;
  38.     UINT8    latch[2];
  39. };
  40.  
  41. struct scroll_position
  42. {
  43.     UINT16     scanline;
  44.     UINT16     x, y;
  45.     UINT8     gfxbank;
  46. };
  47.  
  48.  
  49. /* video RAM */
  50. UINT8 *leland_video_ram;
  51. UINT8 *ataxx_qram;
  52. UINT8 leland_last_scanline_int;
  53.  
  54. /* video RAM bitmap drawing */
  55. static struct vram_state_data vram_state[2];
  56. static UINT8 sync_next_write;
  57.  
  58. /* partial screen updating */
  59. static UINT8 *video_ram_copy;
  60. static int next_update_scanline;
  61.  
  62. /* scroll background registers */
  63. static UINT16 xscroll;
  64. static UINT16 yscroll;
  65. static UINT8 gfxbank;
  66. static UINT8 scroll_index;
  67. static struct scroll_position scroll_pos[VIDEO_HEIGHT];
  68.  
  69. static UINT32 *ataxx_pen_usage;
  70.  
  71.  
  72. /* sound routines */
  73. extern UINT8 leland_dac_control;
  74.  
  75. extern void leland_dac_update(int indx, UINT8 *base);
  76.  
  77. /* bitmap blending routines */
  78. static void draw_bitmap_8(struct osd_bitmap *bitmap);
  79. static void draw_bitmap_16(struct osd_bitmap *bitmap);
  80.  
  81.  
  82.  
  83. /*************************************
  84.  *
  85.  *    Start video hardware
  86.  *
  87.  *************************************/
  88.  
  89. int leland_vh_start(void)
  90. {
  91.     void leland_vh_stop(void);
  92.  
  93.     /* allocate memory */
  94.     leland_video_ram = malloc(VRAM_SIZE);
  95.     video_ram_copy = malloc(VRAM_SIZE);
  96.  
  97.     /* error cases */
  98.     if (!leland_video_ram || !video_ram_copy)
  99.     {
  100.         leland_vh_stop();
  101.         return 1;
  102.     }
  103.  
  104.     /* reset videoram */
  105.     memset(leland_video_ram, 0, VRAM_SIZE);
  106.     memset(video_ram_copy, 0, VRAM_SIZE);
  107.  
  108.     /* reset scrolling */
  109.     scroll_index = 0;
  110.     memset(scroll_pos, 0, sizeof(scroll_pos));
  111.  
  112.     return 0;
  113. }
  114.  
  115.  
  116. int ataxx_vh_start(void)
  117. {
  118.     void ataxx_vh_stop(void);
  119.  
  120.     const struct GfxElement *gfx = Machine->gfx[0];
  121.     UINT32 usage[2];
  122.     int i, x, y;
  123.  
  124.     /* first do the standard stuff */
  125.     if (leland_vh_start())
  126.         return 1;
  127.  
  128.     /* allocate memory */
  129.     ataxx_qram = malloc(QRAM_SIZE);
  130.     ataxx_pen_usage = malloc(gfx->total_elements * 2 * sizeof(UINT32));
  131.  
  132.     /* error cases */
  133.     if (!ataxx_qram || !ataxx_pen_usage)
  134.     {
  135.         ataxx_vh_stop();
  136.         return 1;
  137.     }
  138.  
  139.     /* build up color usage */
  140.     for (i = 0; i < gfx->total_elements; i++)
  141.     {
  142.         UINT8 *src = gfx->gfxdata + i * gfx->char_modulo;
  143.  
  144.         usage[0] = usage[1] = 0;
  145.         for (y = 0; y < gfx->height; y++)
  146.         {
  147.             for (x = 0; x < gfx->width; x++)
  148.             {
  149.                 int color = src[x];
  150.                 usage[color >> 5] |= 1 << (color & 31);
  151.             }
  152.             src += gfx->line_modulo;
  153.         }
  154.         ataxx_pen_usage[i * 2 + 0] = usage[0];
  155.         ataxx_pen_usage[i * 2 + 1] = usage[1];
  156.     }
  157.  
  158.     /* reset QRAM */
  159.     memset(ataxx_qram, 0, QRAM_SIZE);
  160.     return 0;
  161. }
  162.  
  163.  
  164.  
  165. /*************************************
  166.  *
  167.  *    Stop video hardware
  168.  *
  169.  *************************************/
  170.  
  171. void leland_vh_stop(void)
  172. {
  173.     if (leland_video_ram)
  174.         free(leland_video_ram);
  175.     leland_video_ram = NULL;
  176.  
  177.     if (video_ram_copy)
  178.         free(video_ram_copy);
  179.     video_ram_copy = NULL;
  180. }
  181.  
  182.  
  183. void ataxx_vh_stop(void)
  184. {
  185.     leland_vh_stop();
  186.  
  187.     if (ataxx_qram)
  188.         free(ataxx_qram);
  189.     ataxx_qram = NULL;
  190.  
  191.     if (ataxx_pen_usage)
  192.         free(ataxx_pen_usage);
  193.     ataxx_pen_usage = NULL;
  194. }
  195.  
  196.  
  197.  
  198. /*************************************
  199.  *
  200.  *    Scrolling and banking
  201.  *
  202.  *************************************/
  203.  
  204. WRITE_HANDLER( leland_gfx_port_w )
  205. {
  206.     int scanline = leland_last_scanline_int;
  207.     struct scroll_position *scroll;
  208.  
  209.     /* treat anything during the VBLANK as scanline 0 */
  210.     if (scanline > Machine->drv->visible_area.max_y)
  211.         scanline = 0;
  212.  
  213.     /* adjust the proper scroll value */
  214.     switch (offset)
  215.     {
  216.         case -1:
  217.             gfxbank = data;
  218.             break;
  219.         case 0:
  220.             xscroll = (xscroll & 0xff00) | (data & 0x00ff);
  221.             break;
  222.         case 1:
  223.             xscroll = (xscroll & 0x00ff) | ((data << 8) & 0xff00);
  224.             break;
  225.         case 2:
  226.             yscroll = (yscroll & 0xff00) | (data & 0x00ff);
  227.             break;
  228.         case 3:
  229.             yscroll = (yscroll & 0x00ff) | ((data << 8) & 0xff00);
  230.             break;
  231.     }
  232.  
  233.     /* update if necessary */
  234.     scroll = &scroll_pos[scroll_index];
  235.     if (xscroll != scroll->x || yscroll != scroll->y || gfxbank != scroll->gfxbank)
  236.     {
  237.         /* determine which entry to use */
  238.         if (scroll->scanline != scanline && scroll_index < VIDEO_HEIGHT - 1)
  239.             scroll++, scroll_index++;
  240.  
  241.         /* fill in the data */
  242.         scroll->scanline = scanline;
  243.         scroll->x = xscroll;
  244.         scroll->y = yscroll;
  245.         scroll->gfxbank = gfxbank;
  246.     }
  247. }
  248.  
  249.  
  250.  
  251. /*************************************
  252.  *
  253.  *    Video address setting
  254.  *
  255.  *************************************/
  256.  
  257. void leland_video_addr_w(int offset, int data, int num)
  258. {
  259.     struct vram_state_data *state = vram_state + num;
  260.  
  261.     if (!offset)
  262.     {
  263.         state->addr = (state->addr & 0x7f00) | (data & 0x00ff);
  264.         state->plane = 0;
  265.     }
  266.     else
  267.     {
  268.         state->addr = ((data << 8) & 0x7f00) | (state->addr & 0x00ff);
  269.         state->plane = 0;
  270.     }
  271.  
  272.     if (num == 0)
  273.         sync_next_write = (state->addr >= 0x7800);
  274. }
  275.  
  276.  
  277.  
  278. /*************************************
  279.  *
  280.  *    Flush data from VRAM into our copy
  281.  *
  282.  *************************************/
  283.  
  284. static void update_for_scanline(int scanline)
  285. {
  286.     int i;
  287.  
  288.     /* skip if we're behind the times */
  289.     if (scanline <= next_update_scanline)
  290.         return;
  291.  
  292.     /* update all scanlines */
  293.     for (i = next_update_scanline; i < scanline; i++)
  294.     {
  295.         memcpy(&video_ram_copy[i * 128 + VRAM_LO], &leland_video_ram[i * 128 + VRAM_LO], 0x51);
  296.         memcpy(&video_ram_copy[i * 128 + VRAM_HI], &leland_video_ram[i * 128 + VRAM_HI], 0x51);
  297.     }
  298.  
  299.     /* set the new last update */
  300.     next_update_scanline = scanline;
  301. }
  302.  
  303.  
  304.  
  305. /*************************************
  306.  *
  307.  *    Common video RAM read
  308.  *
  309.  *************************************/
  310.  
  311. int leland_vram_port_r(int offset, int num)
  312. {
  313.     struct vram_state_data *state = vram_state + num;
  314.     int addr = state->addr;
  315.     int plane = state->plane;
  316.     int inc = (offset >> 3) & 1;
  317.     int ret;
  318.  
  319.     switch (offset & 7)
  320.     {
  321.         case 3:    /* read hi/lo (alternating) */
  322.             ret = leland_video_ram[addr + plane * VRAM_HI];
  323.             addr += inc & plane;
  324.             plane ^= 1;
  325.             break;
  326.  
  327.         case 5:    /* read hi */
  328.             ret = leland_video_ram[addr + VRAM_HI];
  329.             addr += inc;
  330.             break;
  331.  
  332.         case 6:    /* read lo */
  333.             ret = leland_video_ram[addr + VRAM_LO];
  334.             addr += inc;
  335.             break;
  336.  
  337.         default:
  338.             logerror("CPU #%d %04x Warning: Unknown video port %02x read (address=%04x)\n",
  339.                         cpu_getactivecpu(),cpu_get_pc(), offset, addr);
  340.             ret = 0;
  341.             break;
  342.     }
  343.     state->addr = addr & 0x7fff;
  344.     state->plane = plane;
  345.  
  346.     if (LOG_COMM && addr >= 0x7800)
  347.         logerror("%04X:%s comm read %04X = %02X\n", cpu_getpreviouspc(), num ? "slave" : "master", addr, ret);
  348.  
  349.     return ret;
  350. }
  351.  
  352.  
  353.  
  354. /*************************************
  355.  *
  356.  *    Common video RAM write
  357.  *
  358.  *************************************/
  359.  
  360. void leland_vram_port_w(int offset, int data, int num)
  361. {
  362.     struct vram_state_data *state = vram_state + num;
  363.     int addr = state->addr;
  364.     int plane = state->plane;
  365.     int inc = (offset >> 3) & 1;
  366.     int trans = (offset >> 4) & num;
  367.  
  368.     /* if we're writing "behind the beam", make sure we've cached what was there */
  369.     if (addr < 0x7800)
  370.     {
  371.         int cur_scanline = cpu_getscanline();
  372.         int mod_scanline = addr / 0x80;
  373.  
  374.         if (cur_scanline != next_update_scanline && mod_scanline < cur_scanline)
  375.             update_for_scanline(cur_scanline);
  376.     }
  377.  
  378.     if (LOG_COMM && addr >= 0x7800)
  379.         logerror("%04X:%s comm write %04X = %02X\n", cpu_getpreviouspc(), num ? "slave" : "master", addr, data);
  380.  
  381.     /* based on the low 3 bits of the offset, update the destination */
  382.     switch (offset & 7)
  383.     {
  384.         case 1:    /* write hi = data, lo = latch */
  385.             leland_video_ram[addr + VRAM_HI] = data;
  386.             leland_video_ram[addr + VRAM_LO] = state->latch[0];
  387.             addr += inc;
  388.             break;
  389.  
  390.         case 2:    /* write hi = latch, lo = data */
  391.             leland_video_ram[addr + VRAM_HI] = state->latch[1];
  392.             leland_video_ram[addr + VRAM_LO] = data;
  393.             addr += inc;
  394.             break;
  395.  
  396.         case 3:    /* write hi/lo = data (alternating) */
  397.             if (trans)
  398.             {
  399.                 if (!(data & 0xf0)) data |= leland_video_ram[addr + plane * VRAM_HI] & 0xf0;
  400.                 if (!(data & 0x0f)) data |= leland_video_ram[addr + plane * VRAM_HI] & 0x0f;
  401.             }
  402.                leland_video_ram[addr + plane * VRAM_HI] = data;
  403.             addr += inc & plane;
  404.             plane ^= 1;
  405.             break;
  406.  
  407.         case 5:    /* write hi = data */
  408.             state->latch[1] = data;
  409.             if (trans)
  410.             {
  411.                 if (!(data & 0xf0)) data |= leland_video_ram[addr + VRAM_HI] & 0xf0;
  412.                 if (!(data & 0x0f)) data |= leland_video_ram[addr + VRAM_HI] & 0x0f;
  413.             }
  414.             leland_video_ram[addr + VRAM_HI] = data;
  415.             addr += inc;
  416.             break;
  417.  
  418.         case 6:    /* write lo = data */
  419.             state->latch[0] = data;
  420.             if (trans)
  421.             {
  422.                 if (!(data & 0xf0)) data |= leland_video_ram[addr + VRAM_LO] & 0xf0;
  423.                 if (!(data & 0x0f)) data |= leland_video_ram[addr + VRAM_LO] & 0x0f;
  424.             }
  425.             leland_video_ram[addr + VRAM_LO] = data;
  426.             addr += inc;
  427.             break;
  428.  
  429.         default:
  430.             logerror("CPU #%d %04x Warning: Unknown video port %02x write (address=%04x value=%02x)\n",
  431.                         cpu_getactivecpu(),cpu_get_pc(), offset, addr);
  432.             break;
  433.     }
  434.  
  435.     /* update the address and plane */
  436.     state->addr = addr & 0x7fff;
  437.     state->plane = plane;
  438. }
  439.  
  440.  
  441.  
  442. /*************************************
  443.  *
  444.  *    Master video RAM read/write
  445.  *
  446.  *************************************/
  447.  
  448. WRITE_HANDLER( leland_master_video_addr_w )
  449. {
  450.     leland_video_addr_w(offset, data, 0);
  451. }
  452.  
  453.  
  454. static void leland_delayed_mvram_w(int param)
  455. {
  456.     int num = (param >> 16) & 1;
  457.     int offset = (param >> 8) & 0xff;
  458.     int data = param & 0xff;
  459.     leland_vram_port_w(offset, data, num);
  460. }
  461.  
  462.  
  463. WRITE_HANDLER( leland_mvram_port_w )
  464. {
  465.     if (sync_next_write)
  466.     {
  467.         timer_set(TIME_NOW, 0x00000 | (offset << 8) | data, leland_delayed_mvram_w);
  468.         sync_next_write = 0;
  469.     }
  470.     else
  471.         leland_vram_port_w(offset, data, 0);
  472. }
  473.  
  474.  
  475. READ_HANDLER( leland_mvram_port_r )
  476. {
  477.     return leland_vram_port_r(offset, 0);
  478. }
  479.  
  480.  
  481.  
  482. /*************************************
  483.  *
  484.  *    Slave video RAM read/write
  485.  *
  486.  *************************************/
  487.  
  488. WRITE_HANDLER( leland_slave_video_addr_w )
  489. {
  490.     leland_video_addr_w(offset, data, 1);
  491. }
  492.  
  493. WRITE_HANDLER( leland_svram_port_w )
  494. {
  495.     leland_vram_port_w(offset, data, 1);
  496. }
  497.  
  498. READ_HANDLER( leland_svram_port_r )
  499. {
  500.     return leland_vram_port_r(offset, 1);
  501. }
  502.  
  503.  
  504.  
  505. /*************************************
  506.  *
  507.  *    Ataxx master video RAM read/write
  508.  *
  509.  *************************************/
  510.  
  511. WRITE_HANDLER( ataxx_mvram_port_w )
  512. {
  513.     offset = ((offset >> 1) & 0x07) | ((offset << 3) & 0x08) | (offset & 0x10);
  514.     if (sync_next_write)
  515.     {
  516.         timer_set(TIME_NOW, 0x00000 | (offset << 8) | data, leland_delayed_mvram_w);
  517.         sync_next_write = 0;
  518.     }
  519.     else
  520.         leland_vram_port_w(offset, data, 0);
  521. }
  522.  
  523.  
  524. WRITE_HANDLER( ataxx_svram_port_w )
  525. {
  526.     offset = ((offset >> 1) & 0x07) | ((offset << 3) & 0x08) | (offset & 0x10);
  527.     leland_vram_port_w(offset, data, 1);
  528. }
  529.  
  530.  
  531.  
  532. /*************************************
  533.  *
  534.  *    Ataxx slave video RAM read/write
  535.  *
  536.  *************************************/
  537.  
  538. READ_HANDLER( ataxx_mvram_port_r )
  539. {
  540.     offset = ((offset >> 1) & 0x07) | ((offset << 3) & 0x08) | (offset & 0x10);
  541.     return leland_vram_port_r(offset, 0);
  542. }
  543.  
  544.  
  545. READ_HANDLER( ataxx_svram_port_r )
  546. {
  547.     offset = ((offset >> 1) & 0x07) | ((offset << 3) & 0x08) | (offset & 0x10);
  548.     return leland_vram_port_r(offset, 1);
  549. }
  550.  
  551.  
  552.  
  553. /*************************************
  554.  *
  555.  *    End-of-frame routine
  556.  *
  557.  *************************************/
  558.  
  559. static void scanline_reset(int param)
  560. {
  561.     /* flush the remaining scanlines */
  562.     update_for_scanline(256);
  563.     next_update_scanline = 0;
  564.  
  565.     /* update the DACs if they're on */
  566.     if (!(leland_dac_control & 0x01))
  567.         leland_dac_update(0, &video_ram_copy[VRAM_LO + 0x50]);
  568.     if (!(leland_dac_control & 0x02))
  569.         leland_dac_update(1, &video_ram_copy[VRAM_HI + 0x50]);
  570.     leland_dac_control = 3;
  571. }
  572.  
  573.  
  574. void leland_vh_eof(void)
  575. {
  576.     /* reset scrolling */
  577.     scroll_index = 0;
  578.     scroll_pos[0].scanline = 0;
  579.     scroll_pos[0].x = xscroll;
  580.     scroll_pos[0].y = yscroll;
  581.     scroll_pos[0].gfxbank = gfxbank;
  582.  
  583.     /* update anything remaining */
  584.     update_for_scanline(VIDEO_HEIGHT * 8);
  585.  
  586.     /* set a timer to go off at the top of the frame */
  587.     timer_set(cpu_getscanlinetime(0), 0, scanline_reset);
  588. }
  589.  
  590.  
  591.  
  592. /*************************************
  593.  *
  594.  *    ROM-based refresh routine
  595.  *
  596.  *************************************/
  597.  
  598. void leland_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  599. {
  600.     const UINT8 *background_prom = memory_region(REGION_USER1);
  601.     const struct GfxElement *gfx = Machine->gfx[0];
  602.     int total_elements = gfx->total_elements;
  603.     UINT8 background_usage[8];
  604.     int x, y, chunk;
  605.  
  606.     /* update anything remaining */
  607.     update_for_scanline(VIDEO_HEIGHT * 8);
  608.  
  609.     /* loop over scrolling chunks */
  610.     /* it's okay to do this before the palette calc because */
  611.     /* these values are raw indexes, not pens */
  612.     memset(background_usage, 0, sizeof(background_usage));
  613.     for (chunk = 0; chunk <= scroll_index; chunk++)
  614.     {
  615.         int char_bank = ((scroll_pos[chunk].gfxbank >> 4) & 0x03) * 0x0400;
  616.         int prom_bank = ((scroll_pos[chunk].gfxbank >> 3) & 0x01) * 0x2000;
  617.  
  618.         /* determine scrolling parameters */
  619.         int xfine = scroll_pos[chunk].x % 8;
  620.         int yfine = scroll_pos[chunk].y % 8;
  621.         int xcoarse = scroll_pos[chunk].x / 8;
  622.         int ycoarse = scroll_pos[chunk].y / 8;
  623.         struct rectangle clip;
  624.  
  625.         /* make a clipper */
  626.         clip = Machine->drv->visible_area;
  627.         if (chunk != 0)
  628.             clip.min_y = scroll_pos[chunk].scanline;
  629.         if (chunk != scroll_index)
  630.             clip.max_y = scroll_pos[chunk + 1].scanline - 1;
  631.  
  632.         /* draw what's visible to the main bitmap */
  633.         for (y = clip.min_y / 8; y < clip.max_y / 8 + 2; y++)
  634.         {
  635.             int ysum = ycoarse + y;
  636.             for (x = 0; x < VIDEO_WIDTH + 1; x++)
  637.             {
  638.                 int xsum = xcoarse + x;
  639.                 int offs = ((xsum << 0) & 0x000ff) |
  640.                            ((ysum << 8) & 0x01f00) |
  641.                            prom_bank |
  642.                            ((ysum << 9) & 0x1c000);
  643.                 int code = background_prom[offs] |
  644.                            ((ysum << 2) & 0x300) |
  645.                            char_bank;
  646.                 int color = (code >> 5) & 7;
  647.  
  648.                 /* draw to the bitmap */
  649.                 drawgfx(bitmap, gfx,
  650.                         code, 8 * color, 0, 0,
  651.                         8 * x - xfine, 8 * y - yfine,
  652.                         &clip, TRANSPARENCY_NONE_RAW, 0);
  653.  
  654.                 /* update color usage */
  655.                 background_usage[color] |= gfx->pen_usage[code & (total_elements - 1)];
  656.             }
  657.         }
  658.     }
  659.  
  660.     /* build the palette */
  661.     palette_init_used_colors();
  662.     for (y = 0; y < 8; y++)
  663.     {
  664.         UINT8 usage = background_usage[y];
  665.         for (x = 0; x < 8; x++)
  666.             if (usage & (1 << x))
  667.             {
  668.                 int p;
  669.                 for (p = 0; p < 16; p++)
  670.                     palette_used_colors[p * 64 + y * 8 + x] = PALETTE_COLOR_USED;
  671.             }
  672.     }
  673.     palette_recalc();
  674.  
  675.     /* Merge the two bitmaps together */
  676.     if (bitmap->depth == 8)
  677.         draw_bitmap_8(bitmap);
  678.     else
  679.         draw_bitmap_16(bitmap);
  680. }
  681.  
  682.  
  683.  
  684. /*************************************
  685.  *
  686.  *    RAM-based refresh routine
  687.  *
  688.  *************************************/
  689.  
  690. void ataxx_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  691. {
  692.     const struct GfxElement *gfx = Machine->gfx[0];
  693.     int total_elements = gfx->total_elements;
  694.     UINT32 background_usage[2];
  695.     int x, y, chunk;
  696.  
  697.     /* update anything remaining */
  698.     update_for_scanline(VIDEO_HEIGHT * 8);
  699.  
  700.     /* loop over scrolling chunks */
  701.     /* it's okay to do this before the palette calc because */
  702.     /* these values are raw indexes, not pens */
  703.     memset(background_usage, 0, sizeof(background_usage));
  704.     for (chunk = 0; chunk <= scroll_index; chunk++)
  705.     {
  706.         /* determine scrolling parameters */
  707.         int xfine = scroll_pos[chunk].x % 8;
  708.         int yfine = scroll_pos[chunk].y % 8;
  709.         int xcoarse = scroll_pos[chunk].x / 8;
  710.         int ycoarse = scroll_pos[chunk].y / 8;
  711.         struct rectangle clip;
  712.  
  713.         /* make a clipper */
  714.         clip = Machine->drv->visible_area;
  715.         if (chunk != 0)
  716.             clip.min_y = scroll_pos[chunk].scanline;
  717.         if (chunk != scroll_index)
  718.             clip.max_y = scroll_pos[chunk + 1].scanline - 1;
  719.  
  720.         /* draw what's visible to the main bitmap */
  721.         for (y = clip.min_y / 8; y < clip.max_y / 8 + 2; y++)
  722.         {
  723.             int ysum = ycoarse + y;
  724.             for (x = 0; x < VIDEO_WIDTH + 1; x++)
  725.             {
  726.                 int xsum = xcoarse + x;
  727.                 int offs = ((ysum & 0x40) << 9) + ((ysum & 0x3f) << 8) + (xsum & 0xff);
  728.                 int code = ataxx_qram[offs] | ((ataxx_qram[offs + 0x4000] & 0x3f) << 8);
  729.  
  730.                 /* draw to the bitmap */
  731.                 drawgfx(bitmap, gfx,
  732.                         code, 0, 0, 0,
  733.                         8 * x - xfine, 8 * y - yfine,
  734.                         &clip, TRANSPARENCY_NONE_RAW, 0);
  735.  
  736.                 /* update color usage */
  737.                 background_usage[0] |= ataxx_pen_usage[(code & (total_elements - 1)) * 2 + 0];
  738.                 background_usage[1] |= ataxx_pen_usage[(code & (total_elements - 1)) * 2 + 1];
  739.             }
  740.         }
  741.     }
  742.  
  743.     /* build the palette */
  744.     palette_init_used_colors();
  745.     for (y = 0; y < 2; y++)
  746.     {
  747.         UINT32 usage = background_usage[y];
  748.         for (x = 0; x < 32; x++)
  749.             if (usage & (1 << x))
  750.             {
  751.                 int p;
  752.                 for (p = 0; p < 16; p++)
  753.                     palette_used_colors[p * 64 + y * 32 + x] = PALETTE_COLOR_USED;
  754.             }
  755.     }
  756.     palette_recalc();
  757.  
  758.     /* Merge the two bitmaps together */
  759.     if (bitmap->depth == 8)
  760.         draw_bitmap_8(bitmap);
  761.     else
  762.         draw_bitmap_16(bitmap);
  763. }
  764.  
  765.  
  766.  
  767. /*************************************
  768.  *
  769.  *    Depth-specific refresh
  770.  *
  771.  *************************************/
  772.  
  773. #define ADJUST_FOR_ORIENTATION(orientation, bitmap, dst, x, y, xadv)    \
  774.     if (orientation)                                                    \
  775.     {                                                                    \
  776.         int dy = bitmap->line[1] - bitmap->line[0];                        \
  777.         int tx = x, ty = y, temp;                                        \
  778.         if (orientation & ORIENTATION_SWAP_XY)                            \
  779.         {                                                                \
  780.             temp = tx; tx = ty; ty = temp;                                \
  781.             xadv = dy / (bitmap->depth / 8);                            \
  782.         }                                                                \
  783.         if (orientation & ORIENTATION_FLIP_X)                            \
  784.         {                                                                \
  785.             tx = bitmap->width - 1 - tx;                                \
  786.             if (!(orientation & ORIENTATION_SWAP_XY)) xadv = -xadv;        \
  787.         }                                                                \
  788.         if (orientation & ORIENTATION_FLIP_Y)                            \
  789.         {                                                                \
  790.             ty = bitmap->height - 1 - ty;                                \
  791.             if ((orientation & ORIENTATION_SWAP_XY)) xadv = -xadv;        \
  792.         }                                                                \
  793.         /* can't lookup line because it may be negative! */                \
  794.         dst = (TYPE *)(bitmap->line[0] + dy * ty) + tx;                    \
  795.     }
  796.  
  797. #define INCLUDE_DRAW_CORE
  798.  
  799. #define DRAW_FUNC draw_bitmap_8
  800. #define TYPE UINT8
  801. #include "leland.c"
  802. #undef TYPE
  803. #undef DRAW_FUNC
  804.  
  805. #define DRAW_FUNC draw_bitmap_16
  806. #define TYPE UINT16
  807. #include "leland.c"
  808. #undef TYPE
  809. #undef DRAW_FUNC
  810.  
  811.  
  812. #else
  813.  
  814.  
  815. /*************************************
  816.  *
  817.  *    Bitmap blending routine
  818.  *
  819.  *************************************/
  820.  
  821. void DRAW_FUNC(struct osd_bitmap *bitmap)
  822. {
  823.     const UINT16 *pens = &Machine->pens[0];
  824.     int orientation = Machine->orientation;
  825.     int x, y;
  826.  
  827.     /* draw any non-transparent scanlines from the VRAM directly */
  828.     for (y = Machine->drv->visible_area.min_y; y <= Machine->drv->visible_area.max_y; y++)
  829.     {
  830.         UINT8 *srclo = &video_ram_copy[y * 128 + VRAM_LO];
  831.         UINT8 *srchi = &video_ram_copy[y * 128 + VRAM_HI];
  832.         TYPE *dst = (TYPE *)bitmap->line[y];
  833.         int xadv = 1;
  834.  
  835.         /* adjust in case we're oddly oriented */
  836.         ADJUST_FOR_ORIENTATION(orientation, bitmap, dst, 0, y, xadv);
  837.  
  838.         /* redraw the scanline */
  839.         for (x = 0; x < VIDEO_WIDTH*2; x++)
  840.         {
  841.             UINT16 data = (*srclo++ << 8) | *srchi++;
  842.  
  843.             *dst = pens[*dst | ((data & 0xf000) >> 6)];
  844.             dst += xadv;
  845.             *dst = pens[*dst | ((data & 0x0f00) >> 2)];
  846.             dst += xadv;
  847.             *dst = pens[*dst | ((data & 0x00f0) << 2)];
  848.             dst += xadv;
  849.             *dst = pens[*dst | ((data & 0x000f) << 6)];
  850.             dst += xadv;
  851.         }
  852.     }
  853. }
  854.  
  855. #endif
  856.